package actor
import (
	"net"
	"fmt"
	"github.com/eapache/channels"
	"reflect"
)

type ActorSystem struct {
	Name     string
	user     SimpleActor
	NoSender EmptyActor

}

func System(name string) *ActorSystem {
	system := ActorSystem{
		Name : name,
		NoSender: EmptyActor{},
	}
	user := SimpleActor{
		name: "user",
		context:&Context{
			system : &system,
			children : make(map[string]Actor),
			mailbox:channels.NewResizableChannel(),
			stop_flag: make(chan bool, 1),
		},
	}
	system.user = user
	user.DoReceive(systemReceiver, &user)
	return &system
}

func systemReceiver(message interface{}, sender Actor) {

}

func (this *ActorSystem) ActorOf(name string) SimpleActor {
	return this.user.ActorOf(name)
}

func Register(some interface{}) {

	value := reflect.ValueOf(some)
	doReceiveFunc := value.MethodByName("DoReceive")
	receiveFunc := value.MethodByName("Receive")
	if (doReceiveFunc.IsValid() && receiveFunc.IsValid()) {
		doReceiveFunc.Call([]reflect.Value{receiveFunc, value})
	}
}

func (this *ActorSystem) Start(host string) {
	listener, err := net.Listen("tcp", host)
	if err == nil {
		fmt.Printf("start actor system at %s \n", host)
		go func() {
			for {
				listener.Accept()
			}
		}()
	}else {
		fmt.Println("start actor system fail, ", err.Error())
	}
	//	wait := sync.WaitGroup{}
	//	wait.Add(1)
	//	wait.Wait()
}


